#pragma once

#include <iostream>
#include <memory>
#include <ctime>
#include <thread>
#include <mutex>
#include <shared_mutex>
#include <condition_variable>
#include <string>
#include <unordered_map>
#include <atomic>
#include "LogFileNode.hpp"

namespace yzhzc
{
namespace log
{

class LogFileNodeManager
{
public:

    /**
     * @brief 构造函数，启动后台清理线程。
     */
    LogFileNodeManager()
        : _running(true)
        , _cleanupThread(&LogFileNodeManager::cleanupTask, this)
    {}

    /**
     * @brief 析构函数，停止后台清理线程并等待其结束。
     */
    ~LogFileNodeManager()
    {
        {
            std::unique_lock<std::mutex> lock(_cvMutex);
            _running = false; // 停止后台线程
        }

        _cv.notify_all(); // 唤醒所有等待的线程
        if (_cleanupThread.joinable()) {
            _cleanupThread.join(); // 等待线程结束
        }

        // 遍历 _fileMap 并释放所有 LogFileNode 资源
        std::unique_lock<std::shared_mutex> fileLock(_fileMapMutex);    // 获取 _fileMapMutex 的写锁
        for (auto& [fileDir, node] : _fileMap) {
            if (node) {
                node.reset(); // 释放 std::unique_ptr 管理的资源
            }
        }
    }

    /**
    * @brief 添加文件规则。
    * @param fileDir 文件目录路径
    * @param genPolicy 文件生成策略
    * @param genValue 策略值
    * @param purgePol 文件清理策略
    * @param purgeVal 清理策略值
    */
    LogFileNodeManager& addFileRule(const std::string& filePath,
        TimeUnit genPolicy = TimeUnit::DAILY, int genValue = 1,
        TimeUnit purgePol = TimeUnit::DAILY, int purgeVal = 7)
    {
        std::lock_guard<std::mutex> lock(_temFileMapMutex);
        _temFileMap[filePath] = std::make_unique<LogFileNode>(filePath, genPolicy, genValue, purgePol, purgeVal);

        return *this;
    }


    void applyRules()
    {
        // 确保锁的顺序一致，避免死锁
        std::lock_guard<std::mutex> lock2(_temFileMapMutex);
        {
            std::unique_lock<std::shared_mutex> lock1(_fileMapMutex);    // _fileMapMutex 的写锁

            // 初始化每个 fileNode 的文件流
            for (auto& [fileDir, node] : _temFileMap) {
                node->init();
            }

            // 将临时的 _temFileMap 替换到 _fileMap
            std::swap(_temFileMap, _fileMap);
        }

        // 清空当前的 _fileMap
        _temFileMap.clear();
    }

    /**
     * @brief 写入消息到指定目录的文件。
     * @param fileDir 文件目录路径
     * @param message 要写入的消息
     */
    void writeToFile(const std::string& fileDir, const std::string& message, std::time_t timeNow = 0)
    {
        std::shared_lock<std::shared_mutex> lock(_fileMapMutex);    // _fileMapMutex 的只读锁
        auto it = _fileMap.find(fileDir);
        if (it == _fileMap.end()) return;
        if (!timeNow)timeNow = std::time(nullptr);

        it->second->write(message, timeNow); // 调用对应文件节点的写入方法
    }

private:

    /**
 * @brief 后台清理任务，定期清理过期文件。
 */
    void cleanupTask()
    {
        using namespace std::chrono_literals;
        std::unique_lock<std::mutex> lock(_cvMutex);
        while (_running) {
            // 等待 1 小时，或者被唤醒
            _cv.wait_for(lock, 1h, [this] { return !_running; });
            if (!_running) break; // 如果 _running 为 false，退出循环

            std::shared_lock<std::shared_mutex> fileLock(_fileMapMutex); // _fileMapMutex 的只读
            for (const auto& [dir, node] : _fileMap) {
                // 清理单个文件节点的过期文件
                node->purgeFiles();
            }
        }
    }

private:

    std::unordered_map<std::string, std::unique_ptr<LogFileNode>> _fileMap;
    std::shared_mutex _fileMapMutex;

    std::unordered_map<std::string, std::unique_ptr<LogFileNode>> _temFileMap;
    std::mutex _temFileMapMutex;

    std::atomic<bool> _running;    // 控制后台线程运行状态
    std::thread _cleanupThread;    // 执行定期清除线程

    std::condition_variable _cv;    // 条件变量，用于唤醒线程
    std::mutex _cvMutex;            // 保护条件变量的互斥锁
};
}
}